/**
 *  Copyright (C) 2008-2013  Telosys project org. ( http://www.telosys.org/ )
 *
 *  Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *          http://www.gnu.org/licenses/lgpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.telosys.persistence.database;

import java.sql.DatabaseMetaData;

import org.telosys.persistence.TelosysPersistenceException;
import org.telosys.persistence.connection.ConnectionProvider;
import org.telosys.persistence.dbfeatures.DbFeatures;
import org.telosys.persistence.dbfeatures.DbFeaturesProvider;
import org.telosys.util.ClassUtil;
import org.telosys.util.StrUtil;

/**
 * All objects useful for a database management  <br>
 * 
 * @author Laurent Guerin
 *
 */
public class Database {
	
	private DatabaseConfig     databaseConfig = null ;
	
	private ConnectionProvider connectionProvider = null ;

	private DbFeatures         dbFeatures = null ;
	
	protected Database(DatabaseConfig databaseConfig,
			ConnectionProvider connectionProvider) {
		super();
		
		if ( null == databaseConfig ) { throw new IllegalArgumentException("DatabaseConfig is null") ; }
		if ( null == connectionProvider ) { throw new IllegalArgumentException("ConnectionProvider is null") ; }
		
		this.databaseConfig = databaseConfig;
		this.connectionProvider = connectionProvider;
		
		initDbFeaturesIfSpecificClass() ;
	}

	public int getId() {
		return databaseConfig.getId() ;
	}
	
	public String getName() {
		return databaseConfig.getName();
	}
	
	public DatabaseConfig getDatabaseConfig() {
		return databaseConfig;
	}

	public ConnectionProvider getConnectionProvider() {
		return connectionProvider;
	}
	
	private void initDbFeaturesIfSpecificClass() 
	{
		String dbFeaturesClassName = databaseConfig.getDbFeaturesClassName() ;
		if ( ! StrUtil.nullOrVoid(dbFeaturesClassName) ) {
			//--- Specific class for DbFeatures : try to instantiate...
			Class<?> clazz = ClassUtil.tryToLoadClass(dbFeaturesClassName);
			if ( null == clazz ) {
				throw new TelosysPersistenceException("Cannot load DbFeatures class '" + dbFeaturesClassName + "'");
			}
			else {
				Object object = ClassUtil.createObjectInstance(clazz);
				if ( object != null ) {
					if ( object instanceof DbFeatures ) {
						dbFeatures = (DbFeatures) object ;
					}
					else {
						throw new TelosysPersistenceException("Class '" + dbFeaturesClassName + "' is not a DbFeatures implementation");
					}
				}
				else {
					throw new TelosysPersistenceException("Cannot create instance of class '" + dbFeaturesClassName + "'");
				}
			}
		}
	}
	
	public DbFeatures getDbFeatures(DatabaseMetaData databaseMetaData) 
	{
		//--- If not yet defined 
		if ( null == dbFeatures ) {
			//--- Determine DbFeatures dynamically using DatabaseMetaData
			DbFeaturesProvider dbFeaturesProvider = new DbFeaturesProvider();
			dbFeatures = dbFeaturesProvider.getDbFeatures(databaseMetaData);
		}
		
		if ( null == dbFeatures ) {
			throw new TelosysPersistenceException("Unexpected error : Cannot retrieve DbFeatures");
		}
		
		return dbFeatures ;
	}

	@Override
	public String toString() {
		return "Database [ id:" + databaseConfig.getId()
				+ ", name:" + databaseConfig.getName()
				+ ", connectionProvider:" + connectionProvider.getTypeName() + " ("+ connectionProvider.getType() + ")"
				+ "]";
	}
	
	
}
